<?php
require_once ( "perm_manager.php" );
require_once ( "prefs_manager.php" );
// require_once ( "logger.php" );

define ( "LIWE_ERR_MISSING_METHOD", -1 );
define ( "LIWE_ERR_NOT_LOGGED_IN",  -2 );

/*
Method array

is defined in this way:

	$this->methods = array ( 
				"method_name" => array ( "object_method", "perm_name", is_logged )
			 );

	where:

		``method_name`` 	is the name of the method the class is publishing
		``object_method``	is the name of the method inside the object
		``perm_name``		is the name of the permission needed to invoke this method
					if ``perm_name`` is false, everyone can call the method
		``is_logged``		if the user is currently logged (its UID is != 0)

	$this->actions = array (
				array ( "action descr", "action method (complete url)", "permission" ),
				array ( "Metodo d'esempio", "javascript:method_test()", "test" ),
			 );

	$this->prefs = array (
				"PREF_NAME" => array ( "type", "def_value", "user_selectable" ),
			);

	$this->prefs_names = array (
					"PREF_NAME" => "Txt description",
				);

		
*/
class module_base
{
	var $sess;		// Session
	var $dbm;		// DB Manager
	var $layman;		// Layout Manager

	var $name;		// Module name
	var $methods;		// Module methods
	var $perms;		// Module permissions
	var $actions;		// Module actions
	var $prefs;		// Module prefs
	var $prefs_names;	// Module prefs names
	
	var $perms_loaded;	// Array: (internal) flag to know if the perms have been already loaded from SQL

	// {{{ module_base ( $name )
	function module_base ( $name )
	{
		$this->name = $name;
		$this->perms   = null;
		$this->methods = null;
		$this->actions = null;
		$this->prefs   = null;
		$this->prefs_names = null;

		$this->perms_loaded = null;
		$this->prefs_loaded = null;
	}
	// }}}
	// {{{ class_init ( & $sess, & $dbm, & $layman )
	function class_init ( & $sess, & $dbm, & $layman )
	{
		error_log ( "INIT of: " . $this->name );

		$this->sess 	= & $sess;
		$this->dbm  	= & $dbm;
		$this->layman	= & $layman;

		// Add some default methods
		$this->methods [ "avail_perms" ] = array ( "list_avail_perms", false );
		$this->methods [ "list_all_perms" ] = array ( "list_all_perms", false );
		$this->methods [ "list_menu_actions" ] = array ( "list_menu_actions", false );
		$this->methods [ "list_module_prefs" ] = array ( "list_module_prefs", false );

		$this->_read_prefs ();

		if ( $this->layman ) $this->layman->add_global ( $this->name . "_prefs", $this->_get_prefs_js () );
	}
	// }}}
	// {{{ & invoke ( & $obj, & $params )
	function & invoke ( & $obj, & $params )
	{
		// Resolve the method name from params
		$method = $params [ 1 ];

		// If the object has no methods attribute, return NULL
		if ( ! $obj->methods ) 
		{
			$res    = null;
			return $res;
		}

		// Check for permissions
		$res = & $obj->check_perms ( $method );

		// If ``$res`` is not empty, an error on permissions has occurred
		if ( sizeof ( $res ) ) return $res;

		// Prendo il metodo
		$meth   = @ $obj->methods [ $method ];

		// Se sono arrivato fino a qui, invoco il metodo sulla classe
		$res = call_user_func ( array ( & $obj, $meth [ 0 ] ), array_slice ( $params, 2 ) );

		return $res;
	}
	// }}}
	// {{{ exists ( $method_name )
	function exists ( $method_name )
	{
		return array_key_exists ( $method_name, $this->methods );
	}
	// }}}
	// {{{ check_perms ( $method_name ) 
	function & check_perms ( $method_name )
	{
		$res = array ();

		$meth = @ $this->methods [ $method_name ];

		if ( ! $meth )
		{
			$res [ 'err_code' ] = LIWE_ERR_MISSING_METHOD;
			$res [ 'err_descr' ] = "The method: $method_name does not exist";
			return $res;
		}

		// If the user NEEDS to be logged
		if ( @$meth [ 2 ] ) if ( ! $this->sess->get ( "uid" ) )
		{
			$res [ 'err_code' ] = LIWE_ERR_NOT_LOGGED_IN;
			$res [ 'err_descr' ] = "User must be logged in to continue";
			return $res;
		}

		// If not permission name is set, the user can call this method by default
		$perm = @ $meth [ 1 ];
		if ( ! $perm ) return $res;

		if ( $this->has_perm  ( $perm ) ) return $res;

		$res [ 'err_code' ] = LIWE_ERR_NO_PERMISSIONS;
		$res [ 'err_descr' ] = "You don't have enough permissions to execute: $method_name on " . $this->name;

		return $res;
	}
	// }}}
	// {{{ has_perm ( $perm_name )
	function has_perm ( $perm_name )
	{
		error_log ( "has perm: 1 - mod: " . $this->name . " - $perm_name - user: " . $this->sess->get ( "login" ) );
		// The "root" user always has all permissions
		if ( $this->sess->get ( "login" ) == 'root' ) return true;

		// If the permission in "logged", we just check for the "uid" variable
		if ( ( $perm_name == 'logged' ) && ( $this->sess->get ( "uid" ) ) ) return true;

		error_log ( "has perm: 2" );

		// Load perms from DB
		$this->_read_perms ();

		// Check if the current user actually has the right perms for the operation
		if ( @ $this->perms_loaded [ $perm_name ] == 0 ) return false;	

		error_log ( "has perm: 4" );
		return true;
	}
	// }}}
	// {{{ & list_avail_perms ()
	function & list_avail_perms ()
	{
		$res = Array ();
		$res [ 'err_code' ] = 0;
		$res [ 'perms' ] = Array ();
		
		if ( $this->sess->get ( "login" ) != 'root' )
		{
			$this->_read_perms ();


			foreach ( $this->perms_loaded as $name => $val )
				$res [ 'perms' ] [ $name ] = $val;
		} else {
			foreach ( $this->perms_names as $name )
				$res [ 'perms' ] [ $name ] = 1;
		}

		return $res;
	}
	// }}}
	// {{{ & list_all_perms ()
	function & list_all_perms ()
	{
		$res = Array ();
		$res [ 'err_code' ] = 0;
		$res [ 'perms' ] = Array ();

		// Il valore "3" significa che il permesso e' del modulo
		foreach ( $this->perms_names as $name ) $res [ 'perms' ] [ $name ] = 3;

		return $res;
	}
	// }}}
	// {{{ & list_menu_actions ()
	function & list_menu_actions ()
	{
		$res = Array ();

		if ( ! $this->actions ) return $res;

		foreach ( $this->actions as $act )
		{
			error_log ( "list_menu_actions: {$act[0]} - perm: {$act[2]}" );
			if ( $act [ 2 ] ) 
			{
				if ( $act [ 2 ] == 'logged' )
				{
					if ( $this->sess->get ( "uid" ) == false ) continue;
				} else
					if ( $this->has_perm ( $act [ 2 ] ) == false ) continue;
			}

			error_log ( "*** ADD list_menu_actions: {$act[0]}" );
			$res [] = array ( $act [ 0 ], $act [ 1 ] );
		}

		if ( $this->has_perm ( "config" ) )
			$res [] = array ( "Configurazione", "javascript:" . $this->name . "_configure()" );

		return $res;
	}
	// }}}
	// {{{ & list_module_prefs ()
	function & list_module_prefs ()
	{
		$res = Array ();

		if ( ! $this->prefs ) return $res;

		foreach ( $this->prefs as $pref_name => $values )
		{
			$pdescr = $this->prefs_names [ $pref_name ];
			if ( ! $pdescr ) $pdescr = $pref_name;

			// FIXME: should skip if not manage prefs is valid...
			$res [ $pref_name ] = array ( "label" => $pdescr, "mode" => $values [ 'mode' ], "value" => $values [ 'default' ] );
		}

		$a = array ( "prefs" => $res, "mod_name" => $this->name );
		return $a;
	}
	// }}}
	// {{{ set_perms_names ( & $perms_names )
	function set_perms_names ( & $perms_names )
	{
		$this->perms_names = & $perms_names;
	}
	// }}}
	/* =========================================================================== 
	INTERNAL FUNCTIONS
	=========================================================================== */
	// {{{ _read_perms ()
	function _read_perms ()
	{
		if ( $this->perms_loaded ) return;

		$pm = new PermsManager ( & $this->dbm, & $this->sess );
		$this->perms_loaded = & $pm->read_user ( $this->name, $this->sess->get ( "uid" ) );
	}
	// }}}
	// {{{ _read_prefs ()
	function _read_prefs ()
	{
		if ( ! $this->prefs ) return;
		if ( $this->prefs_loaded ) return;

		$pm = new PrefsManager ( & $this->dbm, & $this->sess );
		$this->prefs_loaded = & $pm->read_prefs ( $this->name, $this->prefs, $this->sess->get ( "uid" ) );

		foreach ( $this->prefs as $key => $val )
			if ( ! array_key_exists ( $key, $this->prefs_loaded ) ) $this->prefs_loaded [ $key ] = $val;
	}
	// }}}

	function _get_prefs_js ()
	{
		require_once ( "js_utils.php" );
		$s = array2js ( $this->prefs_loaded );

		return $s;
	}

}
?>
